#ifndef PLANNER_H
#define PLANNER_H

#include "compiler/parser.h"
#include <memory>
#include <string>
#include <vector>

namespace Execution {
    class PlanNode {
    public:
        virtual ~PlanNode() = default;
        virtual std::string toString() const = 0;
    };

    class CreateTablePlan : public PlanNode {
    public:
        std::string tableName;
        std::vector<std::pair<std::string, std::string>> columns;

        std::string toString() const override {
            std::string result = "CreateTable(" + tableName + ", columns: [";
            for (size_t i = 0; i < columns.size(); ++i) {
                if (i > 0) result += ", ";
                result += columns[i].first + ":" + columns[i].second;
            }
            result += "])";
            return result;
        }
    };

    class InsertPlan : public PlanNode {
    public:
        std::string tableName;
        std::vector<std::string> columns;
        std::vector<std::string> values;

        std::string toString() const override {
            std::string result = "Insert(" + tableName;
            if (!columns.empty()) {
                result += ", columns: [";
                for (size_t i = 0; i < columns.size(); ++i) {
                    if (i > 0) result += ", ";
                    result += columns[i];
                }
                result += "]";
            }
            result += ", values: [";
            for (size_t i = 0; i < values.size(); ++i) {
                if (i > 0) result += ", ";
                result += values[i];
            }
            result += "])";
            return result;
        }
    };

    class SelectPlan : public PlanNode {
    public:
        std::string tableName;
        std::vector<std::string> columns;
        std::string filter;

        std::string toString() const override {
            std::string result = "Select(" + tableName + ", columns: [";
            for (size_t i = 0; i < columns.size(); ++i) {
                if (i > 0) result += ", ";
                result += columns[i];
            }
            result += "]";
            if (!filter.empty()) {
                result += ", filter: " + filter;
            }
            result += ")";
            return result;
        }
    };

    class DeletePlan : public PlanNode {
    public:
        std::string tableName;
        std::string filter;

        std::string toString() const override {
            std::string result = "Delete(" + tableName;
            if (!filter.empty()) {
                result += ", filter: " + filter;
            }
            result += ")";
            return result;
        }
    };    
    // Add UpdatePlan class definition after DeletePlan
    class UpdatePlan : public PlanNode {
    public:
        std::string tableName;
        std::vector<std::pair<std::string, std::string>> columnValues;
        std::string filter;
    
        std::string toString() const override {
            std::string result = "Update(" + tableName + ", values: [";
            for (size_t i = 0; i < columnValues.size(); ++i) {
                if (i > 0) result += ", ";
                result += columnValues[i].first + ":" + columnValues[i].second;
            }
            result += "]";
            if (!filter.empty()) {
                result += ", filter: " + filter;
            }
            result += ")";
            return result;
        }
    };
}

class Planner {
public:
    std::unique_ptr<Execution::PlanNode> createPlan(const std::unique_ptr<AST::Statement>& stmt);

private:
    std::unique_ptr<Execution::PlanNode> createCreateTablePlan(const AST::CreateTableStmt& stmt);
    std::unique_ptr<Execution::PlanNode> createInsertPlan(const AST::InsertStmt& stmt);
    std::unique_ptr<Execution::PlanNode> createSelectPlan(const AST::SelectStmt& stmt);
    std::unique_ptr<Execution::PlanNode> createDeletePlan(const AST::DeleteStmt& stmt);
    std::unique_ptr<Execution::PlanNode> createUpdatePlan(const AST::UpdateStmt& stmt);
    std::string expressionToString(const AST::Expression& expr);
};

#endif // PLANNER_H